﻿using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using Newtonsoft.Json;
using System;
using System.Threading.Tasks;
/*
 * 
 * 系统有三个Group，对应三个角色：
 * 1.服务端 server 提供SignalR/Web服务，以及分发消息     AisinGioro.Server
 * 2.代理客户端 agent 采集消息并提交给服务端             AisinGioro.WinAgent
 * 3.监控客户端 portal 接收服务端消息并展现             AisinGioro.WebPortal
 * 
 * */

namespace AisinGioro.Server.Hubs
{
    using Core;
    using Core.DTOs;
    using Notify;

    [HubName("msgHub")]
    public class MsgHub : Hub
    {
        private INotify _notify;
        public MsgHub()
        {
            _notify = NotifyBase.GetInstance();
        }

        protected string RoleName
        {
            get
            {                
                return Context.QueryString["role"] ?? string.Empty;
            }
        }
        
        public const string RoleName_Agent = "agent";
        public const string RoleName_Portal = "portal";

        #region override conn/disconn methods
        public override Task OnConnected()
        {
            if (!string.IsNullOrEmpty(RoleName))
            {
                Groups.Add(Context.ConnectionId, RoleName); //添加链接到制定组
            }
            LogHelper.Trace("Connect {0}", Context.ConnectionId);
            return base.OnConnected();
        }

        public override Task OnDisconnected(bool stopCalled)
        {
            if (!string.IsNullOrEmpty(RoleName))
            {
                Groups.Remove(Context.ConnectionId, RoleName); //从组中移除链接
            }
            LogHelper.Trace("Disconnect {0}", Context.ConnectionId);
            return base.OnDisconnected(stopCalled);
        }

        public override Task OnReconnected()
        {
            if (!string.IsNullOrEmpty(RoleName))
            {
                Groups.Add(Context.ConnectionId, RoleName); //添加链接到制定组
            }
            LogHelper.Trace("Reconnect {0}", Context.ConnectionId);
            return base.OnReconnected();
        }
        #endregion            

        #region hub methods

        #region server
        /// <summary>
        /// 保持连接（调试）
        /// </summary>
        [HubMethodName("keepAlive")]
        public async Task KeepAlive()
        {
            await Clients.All.broadcast(Context.ConnectionId);
        }

        /// <summary>
        /// 发送-心跳包（代理客户端调用）
        /// </summary>
        [HubMethodName("pushHeartbeat")]
        public async Task PushHeartbeat(HeartbeatDto dto)
        {
            LogHelper.Info("PushHeartbeat: {0}", dto.HostId);
            var itemKey = "Hbt_" + dto.HostId;
            MsgHubCaller.Instance.AliveAgentFamily.SignIn(itemKey);
            await Clients.Group(RoleName_Portal).receiveHeartbeat(dto);
        }

        /// <summary>
        /// 发送-CPU信息（代理客户端调用）
        /// </summary>
        [HubMethodName("pushCPU")]
        public async Task PushCPU(CPUInfoDto dto)
        {
            LogHelper.Info("PushCPU: {0}", JsonConvert.SerializeObject(dto));                        
            await Clients.Group(RoleName_Portal).receiveCPU(dto);

            var itemKey = "CPU_" + dto.HostId;
            if (dto.CpuLoad >= 90)
                MsgHubCaller.Instance.AliveAgentFamily.SendNotifyAsync(itemKey, $"[{dto.HostId}][CPU]_Utilization_{dto.CpuLoad}%");
            else
                MsgHubCaller.Instance.AliveAgentFamily.SignIn(itemKey);
        }

        /// <summary>
        /// 发送-磁盘信息（代理客户端调用）
        /// </summary>
        [HubMethodName("pushDisk")]
        public async Task PushDisk(DiskInfoDto dto)
        {
            LogHelper.Info("PushDisk: {0}", JsonConvert.SerializeObject(dto));            
            await Clients.Group(RoleName_Portal).receiveDisk(dto);
            foreach (var item in dto.Items)
            {
                var itemKey = $"Disk_{dto.HostId}_{item.Label}";
                if (item.DiskLoad >= 90)
                    MsgHubCaller.Instance.AliveAgentFamily.SendNotifyAsync(itemKey, $"[{dto.HostId}][Disk/{item.Label}]_Used_{item.DiskLoad}%");
                else
                    MsgHubCaller.Instance.AliveAgentFamily.SignIn(itemKey);
            }
        }

        /// <summary>
        /// 发送-内存信息（代理客户端调用）
        /// </summary>
        [HubMethodName("pushMemory")]
        public async Task PushMemory(MemoryInfoDto dto)
        {
            LogHelper.Info("PushMemory: {0}", JsonConvert.SerializeObject(dto));
            await Clients.Group(RoleName_Portal).receiveMemory(dto);
            var itemKey = "Mem_" + dto.HostId;
            if (dto.MemoryLoad >= 90)
                MsgHubCaller.Instance.AliveAgentFamily.SendNotifyAsync(itemKey, $"[{dto.HostId}][Memory]_InUse_{dto.MemoryLoad}%");
            else
                MsgHubCaller.Instance.AliveAgentFamily.SignIn(itemKey);
        }

        /// <summary>
        /// 发送-网站连接数信息（代理客户端调用）
        /// </summary>
        [HubMethodName("pushCurrentConnection")]
        public async Task PushCurrentConnection(CurrentConnectionDto dto)
        {
            LogHelper.Info("PushConnection: {0}", JsonConvert.SerializeObject(dto));            
            await Clients.Group(RoleName_Portal).receiveCurrentConnection(dto);
            foreach (var item in dto.Items)
            {
                var itemKey = $"Cons_{dto.HostId}_{item.SiteName}";
                if (item.Total > 500)  //网站连接数超过500发送通知
                    MsgHubCaller.Instance.AliveAgentFamily.SendNotifyAsync(itemKey, $"[{dto.HostId}][Connection]_{item.SiteName}_Total_{item.Total}");
                else
                    MsgHubCaller.Instance.AliveAgentFamily.SignIn(itemKey);
            }
        }
        #endregion

        #region tools
        /// <summary>
        /// 发送-PING输出信息（监控客户端调用）
        /// </summary>
        [HubMethodName("pushPingOutput")]
        public async Task PushPingOutput(string dest)
        {
            LogHelper.Info("PushPingOutput: {0}", dest);
            if (dest.StartsWith("http://", StringComparison.OrdinalIgnoreCase)) dest = dest.Substring(7);
            else if (dest.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) dest = dest.Substring(8);
            await Task.Run(() =>
            {
                OutputMethodHandler output = new OutputMethodHandler(PushMessage);
                new NetworkInfo().PingOutput(dest, output);
            });            
        }

        /// <summary>
        /// 发送-Telnet输出信息（监控客户端调用）
        /// </summary>
        [HubMethodName("pushTelnetOutput")]
        public async Task PushTelnetOutput(string dest, int port)
        {
            LogHelper.Info("PushTelnetOutput: {0}:{1}", dest, port);
            if (dest.StartsWith("http://", StringComparison.OrdinalIgnoreCase)) dest = dest.Substring(7);
            else if (dest.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) dest = dest.Substring(8);
            OutputMethodHandler output = new OutputMethodHandler(PushMessage);
            await new NetworkInfo().TelnetOutput(dest, port, output);
        }

        private void PushMessage(string format, params object[] args)
        {
            var message = string.IsNullOrEmpty(format) ? "<br>" : string.Format(format, args).Replace("<", "&lt;").Replace(">", "&gt;").Replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
            Clients.Client(Context.ConnectionId).receiveMessage(message);
        }
        #endregion

        #endregion
    }
}
